﻿using System;
using System.Diagnostics;
using System.Linq;

namespace UtilityToolsCollect.ObjectsLibrary.ProcessManage
{
    /// <summary>
    /// 获取进程当前cpu利用率
    /// 一段时间的平均以及加权平均利用率
    /// </summary>
    public class CpuUtilizationPercentage:IDisposable
    {
        private static float[] Weightings = { 0.1f, 0.15f, 0.2f, 0.25f, 0.3f };
        private Process m_Process;
        private DateTime LastTime = DateTime.MaxValue, CurrentTime;
        private TimeSpan LastProcessorUsedCpuTime, CurrentProcessorUsedCpuTime;
        private float[] UtilizationRates = new float[5];
        private float[] WeightingsResults = new float[5];
        private int URCurrentPoit = -1;
        private int UtilizationRates5Count = 0;
        private int LogicalProcessorCount = Environment.ProcessorCount;


        public CpuUtilizationPercentage(Process process) { m_Process = process; }

        private void NextValue()
        {
            GetValueStart();

            double interval = (CurrentTime - LastTime).TotalMilliseconds;
            if (interval <= 0) { GetValueEND(); return; }
            if (++URCurrentPoit > 4) URCurrentPoit = 0;
            UtilizationRates[URCurrentPoit] = (float)((CurrentProcessorUsedCpuTime - LastProcessorUsedCpuTime).TotalMilliseconds / interval / LogicalProcessorCount * 100);
            if (UtilizationRates5Count < 5)
                UtilizationRates5Count++;
            
            GetValueEND();
        }

        public float ImmediateValue
        {
            get
            {
                if (m_Process == null) return 0;
                NextValue();
                if (URCurrentPoit < 0) return 0;
                return UtilizationRates[URCurrentPoit];
            }
        }

        public float WeightedAverageValue
        {
            get
            {
                if (m_Process == null) return 0;
                NextValue();
                if (URCurrentPoit < 0) return 0;
                return UtilizationRates5Count < 5 ? UtilizationRates.Average() : WeightedMean();
            }
        }

        private void GetValueStart()
        {
            CurrentTime = DateTime.Now;
            CurrentProcessorUsedCpuTime = m_Process.TotalProcessorTime;
        }

        private void GetValueEND()
        {
            LastTime = CurrentTime;
            LastProcessorUsedCpuTime = CurrentProcessorUsedCpuTime;
        }

        private float WeightedMean()
        {
            for (int i = 0; i < UtilizationRates.Length; i++)
            {
                WeightingsResults[i] = UtilizationRates[i] * Weightings[i];
            }
            return WeightingsResults.Sum();
        }

        #region IDisposable
        private bool disposedValue;
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    UtilizationRates = null!;
                    WeightingsResults = null!;
                    m_Process = null!;
                }

                disposedValue = true;
            }
        }
        ~CpuUtilizationPercentage() { Dispose(disposing: false); }
        public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
        #endregion
    }

}
